﻿using System;
using Microsoft.WindowsAzure.Storage.Table;

namespace Leek.Persistence.Azure
{
    internal static class AzureTableFilterExpressionBuilder
    {
        internal static string BuildQuery(FilterExpression filterExpression)
        {
            if (filterExpression == null)
            {
                return string.Empty;
            }
            if (filterExpression is FilterByProperty)
            {
                return Translate((FilterByProperty)filterExpression);
            }
            else if (filterExpression is BinaryExpression)
            {
                return Translate((BinaryExpression)filterExpression);
            }
            else
            {
                throw new NotSupportedException("Unrecognized filter expression type.");
            }
        }

        private static string Translate(FilterByProperty filterByProperty)
        {
            var propertyName = filterByProperty.PropertyName;
            var comparisonValue = filterByProperty.ComparisonValue;
            string operationString;

            switch (filterByProperty.ComparisonOperation)
            {
                case FilterByProperty.ComparisonOperations.Equal:
                    operationString = QueryComparisons.Equal;
                    break;
                case FilterByProperty.ComparisonOperations.GreaterThan:
                    operationString = QueryComparisons.GreaterThan;
                    break;
                case FilterByProperty.ComparisonOperations.GreaterThanOrEqual:
                    operationString = QueryComparisons.GreaterThanOrEqual;
                    break;
                case FilterByProperty.ComparisonOperations.LessThan:
                    operationString = QueryComparisons.LessThan;
                    break;
                case FilterByProperty.ComparisonOperations.LessThanOrEqual:
                    operationString = QueryComparisons.LessThanOrEqual;
                    break;
                case FilterByProperty.ComparisonOperations.NotEqual:
                    operationString = QueryComparisons.NotEqual;
                    break;
                default:
                    throw new NotSupportedException("Unrecognized property comparison type.");
            }

            return TableQuery.GenerateFilterCondition(propertyName, operationString, comparisonValue.ToString());
        }

        private static string Translate(BinaryExpression binaryExpression)
        {
            var leftSubquery = BuildQuery(binaryExpression.LeftTerm);
            var rightSubquery = BuildQuery(binaryExpression.RightTerm);
            string operatorString;

            switch (binaryExpression.LogicalOperation)
            {
                case BinaryExpression.LogicalOperations.And:
                    operatorString = TableOperators.And;
                    break;
                case BinaryExpression.LogicalOperations.Not:
                    operatorString = TableOperators.Not;
                    break;
                case BinaryExpression.LogicalOperations.Or:
                    operatorString = TableOperators.Or;
                    break;
                default:
                    throw new NotSupportedException("Unrecognized binary expression type.");
            }

            return TableQuery.CombineFilters(leftSubquery, operatorString, rightSubquery);
        }
    }
}
